/**
 * Created by HAM on 16-07-02.
 */

/////////////////////////////////////////////////////////begin//////////////////////////////////////////////////////////

if (undefined === global.__MyActor_actor_id) {
    global.__MyActor_actor_id = 0;
}

if  (undefined === global.__MyActor_trace_error_stack) {
    global.__MyActor_trace_error_stack = false;
}

if (undefined === global.__MyActor_delta_stamp) {
    let tmp = setTimeout(()=>{}, 0);
    if (undefined != tmp._idleStart) {
        global.__MyActor_delta_stamp = (new Date()).valueOf() - tmp._idleStart;
    } else {
        global.__MyActor_delta_stamp = (new Date()).valueOf();
    }
    clearTimeout(tmp);
}

if (undefined === global.__MyActor_trace_buff) {
    global.__MyActor_trace_buff = "";
}

if (undefined === global.__MyActor_hold_count) {
    global.__MyActor_hold_count = 0;
    global.__MyActor_hold_id = undefined;
}

if (undefined === global.__MyActor_exception_handler) {
    global.__MyActor_exception_handler = function (msg, err) {
        console.log(msg, err);
        if (global.__MyActor_trace_error_stack && err.stack) {
            console.log(err.stack);
        }
    };
}

function MsgQueue() {
    let self = this;
    self.__head = self.__tail = null;
    self.__size = 0;
}

MsgQueue.prototype.push_back = function (msg) {
    let self = this;
    let newNode = [msg, null];
    if (!self.__head) {
        self.__head = newNode;
    } else {
        self.__tail[1] = newNode;
    }
    self.__tail = newNode;
    self.__size++;
};

MsgQueue.prototype.push_front = function (msg) {
    let self = this;
    let newNode = [msg, self.__head];
    self.__head = newNode;
    if (!self.__tail) {
        self.__tail = newNode;
    }
    self.__size++;
};

MsgQueue.prototype.transfer_back = function (other) {
    let self = this;
    if (!other.empty()) {
        if (!self.__head) {
            self.__head = other.__head;
        } else {
            self.__tail[1] = other.__head;
        }
        self.__tail = other.__tail;
        self.__size += other.__size;
        other.__size = 0;
        other.__head = other.__tail = null;
    }
};

MsgQueue.prototype.transfer_front = function (other) {
    let self = this;
    if (!other.empty()) {
        if (!self.__head) {
            self.__head = other.__head;
            self.__tail = other.__tail;
        } else {
            other.__tail[1] = self.__head;
            self.__head = other.__head;
        }
        self.__size += other.__size;
        other.__size = 0;
        other.__head = other.__tail = null;
    }
};

MsgQueue.prototype.pop_front = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("msg queue is empty");
    let front = self.__head[0];
    self.__head = self.__head[1];
    self.__size--;
    if (0 == self.__size) {
        self.__tail = null;
    }
    return front;
};

MsgQueue.prototype.front = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("msg queue is empty");
    return self.__head[0];
};

MsgQueue.prototype.back = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("msg queue is empty");
    return self.__tail[0];
};

MsgQueue.prototype.length = function () {
    let self = this;
    return self.__size;
};

MsgQueue.prototype.empty = function () {
    let self = this;
    return 0 == self.__size;
};

MsgQueue.prototype.clear = function () {
    let self = this;
    let it = self.__head;
    while (it) {
        self.__size--;
        let t = it;
        it = it[1];
        t[1] = null;
    }
    self.__head = self.__tail = null;
};

MsgQueue.prototype.swap = function (other) {
    let self = this;
    if (other != self) {
        let t = self.__head;
        self.__head = other.__head;
        other.__head = t;
        t = self.__tail;
        self.__tail = other.__tail;
        other.__tail = t;
        t = self.__size;
        self.__size = other.__size;
        other.__size = t;
    }
};
//----------------------------------------------------------------------------------------------------------------------
function Stack() {
    let self = this;
    self.__stack = new MsgQueue();
}

Stack.prototype.push = function (msg) {
    let self = this;
    self.__stack.push_front(msg);
};

Stack.prototype.pop = function () {
    let self = this;
    return self.__stack.pop_front();
};

Stack.prototype.transfer = function (other) {
    let self = this;
    self.__stack.transfer_back(other);
};

Stack.prototype.front = function () {
    let self = this;
    return self.__stack.front();
};

Stack.prototype.length = function () {
    let self = this;
    return self.__stack.length();
};

Stack.prototype.empty = function () {
    let self = this;
    return self.__stack.empty();
};

Stack.prototype.clear = function () {
    let self = this;
    self.__stack.clear();
};
//----------------------------------------------------------------------------------------------------------------------
function List() {
    let self = this;
    self.__guard = [null, null, null];
    self.__guard[1] = self.__guard[2] = self.__guard;
    self.__size = 0;
}

List.prototype.push_back = function (msg) {
    let self = this;
    self.__size++;
    return self.__guard[2] = self.__guard[2][1] = [msg, self.__guard, self.__guard[2]];
};

List.prototype.push_front = function (msg) {
    let self = this;
    self.__size++;
    return self.__guard[1] = self.__guard[1][2] = [msg, self.__guard[1], self.__guard];
};

List.prototype.transfer_back = function (other) {
    let self = this;
    if (!other.empty()) {
        self.__guard[2][1] = other.__guard[1];
        other.__guard[1][2] = self.__guard[2];
        self.__guard[2] = other.__guard[2];
        self.__guard[2][1] = self.__guard;
        self.__size += other.__size;
        other.__size = 0;
        other.__guard[1] = other.__guard[2] = other.__guard;
    }
};

List.prototype.transfer_front = function (other) {
    let self = this;
    if (!other.empty()) {
        self.__guard[1][2] = other.__guard[2];
        other.__guard[2][1] = self.__guard[1];
        self.__guard[1] = other.__guard[1];
        self.__guard[1][2] = self.__guard;
        self.__size += other.__size;
        other.__size = 0;
        other.__guard[1] = other.__guard[2] = other.__guard;
    }
};

List.prototype.pop_back = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("list is empty");
    return self.erase(self.__guard[2]);
};

List.prototype.pop_front = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("list is empty");
    return self.erase(self.__guard[1]);
};

List.prototype.unshift = function (msg) {
    let self = this;
    return self.push_front(msg);
};

List.prototype.shift = function () {
    let self = this;
    return self.pop_front();
};

List.prototype.push = function (msg) {
    let self = this;
    return self.push_back(msg);
};

List.prototype.pop = function () {
    let self = this;
    return self.pop_back();
};

List.prototype.front = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("list is empty");
    return self.__guard[1][0];
};

List.prototype.back = function () {
    let self = this;
    if (0 == self.__size)
        throw new Error("list is empty");
    return self.__guard[2][0];
};

List.prototype.begin = function () {
    let self = this;
    return self.__guard[1];
};

List.prototype.end = function () {
    let self = this;
    return self.__guard;
};

List.prototype.next = function (node) {
    let self = this;
    if (node == self.__guard)
        throw new Error("list iterator.next overstep");
    return node[2];
};

List.prototype.next_erase = function(node) {
    let self = this;
    if (node == self.__guard)
        throw new Error("list iterator.next overstep");
    let nt = node[2];
    self.erase(node);
    return nt;
};

List.prototype.previous = function (node) {
    let self = this;
    if (node[1] == self.__guard)
        throw new Error("list iterator.previous overstep");
    return node[1];
};

List.prototype.is_end = function (node) {
    let self = this;
    return node == self.__guard;
};

List.prototype.is_invalid = function (node) {
    return !node || !node[1] || !node[2];
};

List.prototype.element = function (node) {
    if (!node[1] || !node[2])
        throw new Error("list node is error");
    return node[0];
};

List.prototype.length = function () {
    let self = this;
    return self.__size;
};

List.prototype.empty = function () {
    let self = this;
    return 0 == self.__size;
};

List.prototype.erase = function (node) {
    let self = this;
    if (0 == self.__size)
        throw new Error("list is empty");
    if (!node[1] || !node[2])
        throw new Error("list node is error");
    self.__size--;
    node[1][2] = node[2];
    node[2][1] = node[1];
    let ele = node[0];
    node[0] = node[1] = node[2] = null;
    return ele;
};

List.prototype.clear = function () {
    let self = this;
    let it = self.__guard[2];
    while (self.__size) {
        self.__size--;
        let t = it;
        it = it[2];
        t[0] = t[1] = t[2] = null;
    }
    self.__guard[1] = self.__guard[2] = self.__guard;
};

List.prototype.swap = function (other) {
    let self = this;
    if (other != self) {
        let t = self.__guard;
        self.__guard = other.__guard;
        other.__guard = t;
        t = self.__size;
        self.__size = other.__size;
        other.__size = t;
    }
};
//----------------------------------------------------------------------------------------------------------------------
function Channel(maxLength = 0) {
    if (maxLength >= 1) {
        let self = this;
        self.__type = MyActor.__msg_type_channel_handle;
        self.__closed = false;
        self.__queue = new MsgQueue();
        self.__push_wait_queue = new List();
        self.__pop_wait_queue = new List();
        self.__max_length = Math.floor(maxLength);
    } else {
        NilChannel.call(this);
        this.__proto__ = NilChannel.prototype;
    }
}

Channel.state_undefined = -1;
Channel.state_ok = 0;
Channel.state_fail = 1;
Channel.state_closed = 2;
Channel.state_cancel = 3;
Channel.state_overtime = 4;

Channel.prototype.push = function (msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__queue.length() == self.__max_length) {
        self.__push_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok) {
                self.push(msg, callback);
            } else {
                MyActor.check_exception_callback("Channel push callback error", ()=> callback(state));
            }
        });
    } else {
        self.__queue.push_back(msg);
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel push callback error", ()=> callback(Channel.state_ok));
    }
};

Channel.prototype.try_push = function (msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel try_push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__queue.length() == self.__max_length) {
        MyActor.check_exception_callback("Channel try_push callback error", ()=> callback(Channel.state_fail));
    } else {
        self.__queue.push_back(msg);
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel try_push callback error", ()=> callback(Channel.state_ok));
    }
};

Channel.prototype.timed_push = function (ms, msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel timed_push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__queue.length() == self.__max_length) {
        if (ms > 0) {
            let tmid;
            let node = self.__push_wait_queue.push_back(function (state) {
                if (tmid) {
                    clearTimeout(tmid);
                }
                if (state == Channel.state_ok) {
                    self.push(msg, callback);
                } else {
                    MyActor.check_exception_callback("Channel timed_push callback error", ()=> callback(state));
                }
            });
            tmid = setTimeout(function () {
                tmid = null;
                let pushWait = self.__push_wait_queue.erase(node);
                pushWait(Channel.state_overtime);
            }, ms);
        } else {
            MyActor.check_exception_callback("Channel timed_push callback error", ()=> callback(Channel.state_overtime));
        }
    } else {
        self.__queue.push_back(msg);
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel timed_push callback error", ()=> callback(Channel.state_ok));
    }
};

Channel.prototype.pop = function (callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (!self.__queue.empty()) {
        let msg = self.__queue.pop_front();
        if (!self.__push_wait_queue.empty()) {
            self.__push_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel pop callback error", ()=> callback(Channel.state_ok, msg));
    } else {
        self.__pop_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok) {
                self.pop(callback);
            } else {
                MyActor.check_exception_callback("Channel pop callback error", ()=> callback(state));
            }
        });
    }
};

Channel.prototype.try_pop = function (callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel try_pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (!self.__queue.empty()) {
        let msg = self.__queue.pop_front();
        if (!self.__push_wait_queue.empty()) {
            self.__push_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel try_pop callback error", ()=> callback(Channel.state_ok, msg));
    } else {
        MyActor.check_exception_callback("Channel try_pop callback error", ()=> callback(Channel.state_fail));
    }
};

Channel.prototype.timed_pop = function (ms, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel timed_pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (!self.__queue.empty()) {
        let msg = self.__queue.pop_front();
        if (!self.__push_wait_queue.empty()) {
            self.__push_wait_queue.pop_front()(Channel.state_ok);
        }
        MyActor.check_exception_callback("Channel timed_pop callback error", ()=> callback(Channel.state_ok, msg));
    } else if (ms > 0) {
        let tmid;
        let node = self.__pop_wait_queue.push_back(function (state) {
            if (tmid) {
                clearTimeout(tmid);
            }
            if (state == Channel.state_ok) {
                self.pop(callback);
            } else {
                MyActor.check_exception_callback("Channel timed_pop callback error", ()=> callback(state));
            }
        });
        tmid = setTimeout(function () {
            tmid = null;
            let popWait = self.__pop_wait_queue.erase(node);
            popWait(Channel.state_overtime);
        }, ms);
    } else {
        MyActor.check_exception_callback("Channel timed_pop callback error", ()=> callback(Channel.state_fail));
    }
};

Channel.prototype.yield_push = function* (msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_push not in actor");
    let inside = true;
    let result = null;
    self.push(msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.yield_try_push = function* (msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_try_push not in actor");
    let inside = true;
    let result = null;
    self.try_push(msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.yield_timed_push = function* (ms, msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_timed_push not in actor");
    let inside = true;
    let result = null;
    self.timed_push(ms, msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.yield_pop = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_pop not in actor");
    let inside = true;
    let result = null;
    self.pop(function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.yield_try_pop = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_try_pop not in actor");
    let inside = true;
    let result = null;
    self.try_pop(function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.yield_timed_pop = function* (ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Channel yield_timed_pop not in actor");
    let inside = true;
    let result = null;
    self.timed_pop(ms, function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

Channel.prototype.append_pop_notify = function (callback, ntfSign) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("Channel append_pop_notify callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (!self.__queue.empty()) {
        ntfSign.__ntf_sign = true;
        ntfSign.__effect = false;
        MyActor.check_exception_callback("Channel append_pop_notify callback error", ()=> callback(Channel.state_ok));
    } else {
        ntfSign.__ntf_sign = false;
        ntfSign.__effect = true;
        ntfSign.__ntf_node = self.__pop_wait_queue.push_back(function (state) {
            ntfSign.__ntf_sign = true;
            MyActor.check_exception_callback("Channel append_pop_notify callback error", ()=> callback(state));
        });
    }
};

Channel.prototype.remove_pop_notify = function (ntfSign) {
    let self = this;
    if (self.__closed) {
        return Channel.state_closed;
    }
    let effect = ntfSign.__effect;
    ntfSign.__effect = false;
    if (!ntfSign.__ntf_sign) {
        ntfSign.__ntf_sign = true;
        self.__pop_wait_queue.erase(ntfSign.__ntf_node);
        return Channel.state_ok;
    } else {
        if (effect && !self.__queue.empty() && !self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
        return Channel.state_fail;
    }
};

Channel.prototype.__has_msg = function () {
    let self = this;
    return !self.__queue.empty();
};

Channel.prototype.close = function () {
    let self = this;
    self.__closed = true;
    self.__queue.clear();
    let tempQueue1 = new List();
    let tempQueue2 = new List();
    self.__push_wait_queue.swap(tempQueue1);
    self.__pop_wait_queue.swap(tempQueue2);
    while (!tempQueue1.empty()) {
        tempQueue1.pop_front()(Channel.state_closed);
    }
    while (!tempQueue2.empty()) {
        tempQueue2.pop_front()(Channel.state_closed);
    }
};

Channel.prototype.reset = function () {
    let self = this;
    self.__closed = false;
};

Channel.prototype.cancel = function () {
    let self = this;
    let tempQueue1 = new List();
    let tempQueue2 = new List();
    self.__push_wait_queue.swap(tempQueue1);
    self.__pop_wait_queue.swap(tempQueue2);
    while (!tempQueue1.empty()) {
        tempQueue1.pop_front()(Channel.state_cancel);
    }
    while (!tempQueue2.empty()) {
        tempQueue2.pop_front()(Channel.state_cancel);
    }
};

Channel.prototype.cancel_push = function () {
    let self = this;
    let tempQueue = new List();
    self.__push_wait_queue.swap(tempQueue);
    while (!tempQueue.empty()) {
        tempQueue.pop_front()(Channel.state_cancel);
    }
};

Channel.prototype.cancel_pop = function () {
    let self = this;
    let tempQueue = new List();
    self.__pop_wait_queue.swap(tempQueue);
    while (!tempQueue.empty()) {
        tempQueue.pop_front()(Channel.state_cancel);
    }
};
//----------------------------------------------------------------------------------------------------------------------
function NilChannel () {
    let self = this;
    self.__type = MyActor.__msg_type_channel_handle;
    self.__has = false;
    self.__msg = undefined;
    self.__closed = false;
    self.__push_wait_queue = new List();
    self.__pop_wait_queue = new List();
}

NilChannel.prototype.push = function (msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        self.__push_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok) {
                self.push(msg, callback);
            } else {
                MyActor.check_exception_callback("NilChannel push callback error", ()=> callback(state));
            }
        });
    } else {
        self.__has = true;
        self.__msg = msg;
        self.__push_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok && !self.__push_wait_queue.empty()) {
                self.__push_wait_queue.pop_front()(Channel.state_ok);
            }
            MyActor.check_exception_callback("NilChannel push callback error", ()=> callback(state));
        });
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
    }
};

NilChannel.prototype.try_push = function (msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel try_push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        MyActor.check_exception_callback("NilChannel try_push callback error", ()=> callback(Channel.state_fail));
    } else {
        self.__has = true;
        self.__msg = msg;
        self.__push_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok && !self.__push_wait_queue.empty()) {
                self.__push_wait_queue.pop_front()(Channel.state_ok);
            }
            MyActor.check_exception_callback("NilChannel try_push callback error", ()=> callback(state));
        });
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
    }
};

NilChannel.prototype.timed_push = function (ms, msg, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel timed_push callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        if (msg > 0) {
            let tmid;
            let node = self.__push_wait_queue.push_back(function (state) {
                if (tmid) {
                    clearTimeout(tmid);
                }
                if (state == Channel.state_ok) {
                    self.push(msg, callback);
                } else {
                    MyActor.check_exception_callback("NilChannel timed_push callback error", ()=> callback(state));
                }
            });
            tmid = setTimeout(function () {
                tmid = null;
                let pushWait = self.__push_wait_queue.erase(node);
                pushWait(Channel.state_overtime);
            }, ms);
        } else {
            MyActor.check_exception_callback("NilChannel timed_push callback error", ()=> callback(Channel.state_overtime));
        }
    } else {
        self.__has = true;
        self.__msg = msg;
        self.__push_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok && !self.__push_wait_queue.empty()) {
                self.__push_wait_queue.pop_front()(Channel.state_ok);
            }
            MyActor.check_exception_callback("NilChannel timed_push callback error", ()=> callback(state));
        });
        if (!self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
    }
};

NilChannel.prototype.pop = function (callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        self.__has = false;
        let msg = self.__msg;
        self.__msg = undefined;
        self.__push_wait_queue.pop_front()(Channel.state_ok);
        MyActor.check_exception_callback("NilChannel pop callback error", ()=> callback(Channel.state_ok, msg));
    } else {
        self.__pop_wait_queue.push_back(function (state) {
            if (state == Channel.state_ok) {
                self.pop(callback);
            } else {
                MyActor.check_exception_callback("NilChannel pop callback error", ()=> callback(state));
            }
        });
    }
};

NilChannel.prototype.try_pop = function (callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel try_pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        self.__has = false;
        let msg = self.__msg;
        self.__msg = undefined;
        self.__push_wait_queue.pop_front()(Channel.state_ok);
        MyActor.check_exception_callback("NilChannel try_pop callback error", ()=> callback(Channel.state_ok, msg));
    } else {
        MyActor.check_exception_callback("NilChannel try_pop callback error", ()=> callback(Channel.state_fail));
    }
};

NilChannel.prototype.timed_pop = function (ms, callback) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel timed_pop callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        self.__has = false;
        let msg = self.__msg;
        self.__msg = undefined;
        self.__push_wait_queue.pop_front()(Channel.state_ok);
        MyActor.check_exception_callback("NilChannel timed_pop callback error", ()=> callback(Channel.state_ok, msg));
    } else if (ms > 0) {
        let tmid;
        let node = self.__pop_wait_queue.push_back(function (state) {
            if (tmid) {
                clearTimeout(tmid);
            }
            if (state == Channel.state_ok) {
                self.pop(callback);
            } else {
                MyActor.check_exception_callback("NilChannel timed_pop callback error", ()=> callback(state));
            }
        });
        tmid = setTimeout(function () {
            tmid = null;
            let popWait = self.__pop_wait_queue.erase(node);
            popWait(Channel.state_overtime);
        }, ms);
    } else {
        MyActor.check_exception_callback("NilChannel timed_pop callback error", ()=> callback(Channel.state_overtime));
    }
};

NilChannel.prototype.yield_push = function* (msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("NilChannel yield_push not in actor");
    let inside = true;
    let result = null;
    self.push(msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.yield_try_push = function* (msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("NilChannel yield_try_push not in actor");
    let inside = true;
    let result = null;
    self.try_push(msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.yield_timed_push = function* (ms, msg) {
    let self = this;
    let host = MyActor.self_actor();
    if (host || !host.__in_actor)
        throw new Error("NilChannel yield_timed_push not in actor");
    let inside = true;
    let result = null;
    self.timed_push(ms, msg, function (state) {
        if (!inside) {
            host.__pull_yield(state);
        } else {
            inside = false;
            result = state;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.yield_pop = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("NilChannel yield_pop not in actor");
    let inside = true;
    let result = null;
    self.pop(function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.yield_try_pop = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (host || !host.__in_actor)
        throw new Error("NilChannel yield_try_pop not in actor");
    let inside = true;
    let result = null;
    self.try_pop(function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.yield_timed_pop = function* (ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("NilChannel yield_timed_pop not in actor");
    let inside = true;
    let result = null;
    self.timed_pop(ms, function (state, msg) {
        if (!inside) {
            host.__pull_yield([state, msg]);
        } else {
            inside = false;
            result = [state, msg];
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

NilChannel.prototype.append_pop_notify = function (callback, ntfSign) {
    let self = this;
    if (self.__closed) {
        MyActor.check_exception_callback("NilChannel append_pop_notify callback error", ()=> callback(Channel.state_closed));
        return;
    }
    if (self.__has) {
        ntfSign.__ntf_sign = true;
        ntfSign.__effect = false;
        MyActor.check_exception_callback("NilChannel append_pop_notify callback error", ()=> callback(Channel.state_ok));
    } else {
        ntfSign.__ntf_sign = false;
        ntfSign.__effect = true;
        ntfSign.__ntf_node = self.__pop_wait_queue.push_back(function (state) {
            ntfSign.__ntf_sign = true;
            MyActor.check_exception_callback("NilChannel append_pop_notify callback error", ()=> callback(state));
        });
    }
};

NilChannel.prototype.remove_pop_notify = function (ntfSign) {
    let self = this;
    if (self.__closed) {
        return Channel.state_closed;
    }
    let effect = ntfSign.__effect;
    ntfSign.__effect = false;
    if (!ntfSign.__ntf_sign) {
        ntfSign.__ntf_sign = true;
        self.__pop_wait_queue.erase(ntfSign.__ntf_node);
        return Channel.state_ok;
    } else {
        if (effect && self.__has && !self.__pop_wait_queue.empty()) {
            self.__pop_wait_queue.pop_front()(Channel.state_ok);
        }
        return Channel.state_fail;
    }
};

NilChannel.prototype.__has_msg = function () {
    let self = this;
    return self.__has;
};

NilChannel.prototype.close = function () {
    let self = this;
    self.__closed = true;
    self.__has = false;
    self.__msg = undefined;
    let tempQueue1 = new List();
    let tempQueue2 = new List();
    self.__push_wait_queue.swap(tempQueue1);
    self.__pop_wait_queue.swap(tempQueue2);
    while (!tempQueue1.empty()) {
        tempQueue1.pop_front()(Channel.state_closed);
    }
    while (!tempQueue2.empty()) {
        tempQueue2.pop_front()(Channel.state_closed);
    }
};

NilChannel.prototype.reset = function () {
    let self = this;
    self.__closed = false;
};

NilChannel.prototype.cancel = function () {
    let self = this;
    let tempQueue1 = new List();
    let tempQueue2 = new List();
    self.__push_wait_queue.swap(tempQueue1);
    self.__pop_wait_queue.swap(tempQueue2);
    while (!tempQueue1.empty()) {
        tempQueue1.pop_front()(Channel.state_cancel);
    }
    while (!tempQueue2.empty()) {
        tempQueue2.pop_front()(Channel.state_cancel);
    }
};

NilChannel.prototype.cancel_push = function () {
    let self = this;
    let tempQueue = new List();
    self.__push_wait_queue.swap(tempQueue);
    while (!tempQueue.empty()) {
        tempQueue.pop_front()(Channel.state_cancel);
    }
};

NilChannel.prototype.cancel_pop = function () {
    let self = this;
    let tempQueue = new List();
    self.__pop_wait_queue.swap(tempQueue);
    while (!tempQueue.empty()) {
        tempQueue.pop_front()(Channel.state_cancel);
    }
};
//----------------------------------------------------------------------------------------------------------------------
function Csp () {
    let self = this;
    self.__type = MyActor.__msg_type_csp_handle;
    self.__sender_queue = new List();
    self.__receiver_queue= new List();
}

Csp.prototype.yield_invoke = function* (...args) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_invoke not in actor");
    let result = null;
    if (!self.__receiver_queue.empty()) {
        let inside = true;
        let dst = self.__receiver_queue.pop_front();
        dst.__pull_yield([function (res) {
            result = res;
            if (!inside) {
                host.__pull_yield();
            } else {
                inside = false;
            }
        }, args]);
        if (inside) {
            inside = false;
            yield null;
        }
    } else {
        self.__sender_queue.push_back([host, function (res) {
            result = res;
            host.__pull_yield();
        }, args]);
        yield null;
    }
    return result;
};

Csp.prototype.yield_timed_invoke = function* (ms,...args) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_timed_invoke not in actor");
    let result = null;
    if (!self.__receiver_queue.empty()) {
        let inside = true;
        let dst = self.__receiver_queue.pop_front();
        dst.__pull_yield([function (res) {
            result = {ok: true, value: res};
            if (!inside) {
                host.__pull_yield();
            } else {
                inside = false;
            }
        }, args]);
        if (inside) {
            inside = false;
            yield null;
        }
    } else {
        let node = self.__sender_queue.push_back([host, function (res) {
            result = {ok: true, value: res};
            host.__pull_yield();
        }, args]);
        host.__timer_out(function () {
            self.__sender_queue.erase(node);
            result = {ok: false};
            host.__pull_yield();
        }, ms);
        yield null;
    }
    return result;
};

Csp.prototype.yield_try_invoke = function* (...args) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_try_invoke not in actor");
    let result = null;
    if (!self.__receiver_queue.empty()) {
        let inside = true;
        let dst = self.__receiver_queue.pop_front();
        dst.__pull_yield([function (res) {
            result = {ok: true, value: res};
            if (!inside) {
                host.__pull_yield();
            } else {
                inside = false;
            }
        }, args]);
        if (inside) {
            inside = false;
            yield null;
        }
    } else {
        result = {ok: false};
    }
    return result;
};

Csp.prototype.yield_wait = function* (handler) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_wait not in actor");
    if (!self.__sender_queue.empty()) {
        let msg = self.__sender_queue.pop_front();
        msg[0].__cancel_timer();
        msg[1](yield* handler.apply(null, msg[2]));
    } else {
        let [reply, args] = yield self.__receiver_queue.push_back(host);
        reply(yield* handler.apply(null, args));
    }
};

Csp.prototype.yield_timed_wait = function* (ms, handler) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_timed_wait not in actor");
    if (!self.__sender_queue.empty()) {
        let msg = self.__sender_queue.pop_front();
        msg[0].__cancel_timer();
        msg[1](yield* handler.apply(null, msg[2]));
        return false;
    } else {
        let node = self.__receiver_queue.push_back(host);
        let [reply, args] = yield host.__timer_out(function () {
            self.__receiver_queue.erase(node);
            host.__pull_yield();
        }, ms);
        host.__cancel_timer();
        if (reply) {
            reply(yield* handler.apply(null, args));
            return false;
        } else {
            return true;
        }
    }
};

Csp.prototype.yield_try_wait = function* (handler) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("csp yield_try_wait not in actor");
    if (!self.__sender_queue.empty()) {
        let msg = self.__sender_queue.pop_front();
        msg[0].__cancel_timer();
        msg[1](yield* handler.apply(null, msg[2]));
        return true;
    } else {
        return false;
    }
};
//----------------------------------------------------------------------------------------------------------------------
function Mutex() {
    let self = this;
    self.__wait_queue = new List();
    self.__inside_id = 0;
    self.__inside_count = 0
}

Mutex.prototype.yield_lock = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Mutex yield_lock not in actor");
    if (0 == self.__inside_id) {
        self.__inside_id = host.__actor_id;
        self.__inside_count = 1;
    } else if (self.__inside_id == host.__actor_id) {
        self.__inside_count++;
    } else {
        self.__wait_queue.push_back(host);
        yield null;
    }
};

Mutex.prototype.try_lock = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Mutex yield_try_lock not in actor");
    if (0 == self.__inside_id) {
        self.__inside_id = host.__actor_id;
        self.__inside_count = 1;
    } else if (self.__inside_id == host.__actor_id) {
        self.__inside_count++;
    } else {
        return false;
    }
    return true;
};

Mutex.prototype.yield_timed_lock = function* (ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Mutex yield_timed_lock not in actor");
    if (0 == self.__inside_id) {
        self.__inside_id = host.__actor_id;
        self.__inside_count = 1;
    } else if (self.__inside_id == host.__actor_id) {
        self.__inside_count++;
    } else {
        let node = self.__wait_queue.push_back(host);
        host.__timer_out(function() {
            self.__wait_queue.erase(node);
            host.__pull_yield(false);
        }, ms);
        return yield null;
    }
    return false;
};

Mutex.prototype.unlock = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("Mutex yield_timed_lock not in actor");
    if (self.__inside_id != host.__actor_id || self.__inside_count <= 0) {
        throw new Error("unlock error");
    }
    self.__inside_count--;
    if (0 == self.__inside_count) {
        if (!self.__wait_queue.empty()) {
            let ele = self.__wait_queue.pop_front();
            self.__inside_id = ele.__actor_id;
            self.__inside_count = 1;
            if (ele.__timer_completed) {
                ele.__pull_yield();
            } else {
                ele.__cancel_timer();
                ele.__pull_yield(true);
            }
        } else {
            self.__inside_id = 0;
        }
    }
};
//----------------------------------------------------------------------------------------------------------------------
function SharedMutex() {
    let self = this;
    self.__upgrade_mutex = new Mutex();
    self.__wait_queue = new List();
    self.__shared_map = new Map();
}

SharedMutex.prototype.yield_lock = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_lock not in actor");
    if (0 == self.__shared_map.size && (!self.__upgrade_mutex.__inside_id || host.__actor_id == self.__upgrade_mutex.__inside_id)) {
        self.__upgrade_mutex.__inside_id = host.__actor_id;
        self.__upgrade_mutex.__inside_count++;
    } else {
        self.__wait_queue.push_back({wait: host, state: 1});
        yield null;
    }
};

SharedMutex.prototype.try_lock = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex try_lock not in actor");
    if (self.__inside_id != host.__actor_id || self.__inside_count <= 0) {
        throw new Error("try_lock error");
    }
    if (0 == self.__shared_map.size && (!self.__upgrade_mutex.__inside_id || host.__actor_id == self.__upgrade_mutex.__inside_id)) {
        self.__upgrade_mutex.__inside_id = host.__actor_id;
        self.__upgrade_mutex.__inside_count++;
        return true;
    }
    return false;
};

SharedMutex.prototype.yield_timed_lock = function* (ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_timed_lock not in actor");
    if (0 == self.__shared_map.size && (!self.__upgrade_mutex.__inside_id || host.__actor_id == self.__upgrade_mutex.__inside_id)) {
        self.__upgrade_mutex.__inside_id = host.__actor_id;
        self.__upgrade_mutex.__inside_count++;
        return true;
    } else {
        let node = self.__wait_queue.push_back({wait: host, state: 1});
        host.__timer_out(function () {
            self.__wait_queue.erase(node);
            host.__pull_yield(false);
        }, ms);
        return yield null;
    }
};

SharedMutex.prototype.yield_lock_shared = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_lock_shared not in actor");
    if (0 != self.__shared_map.size || !self.__upgrade_mutex.__inside_id) {
        if (self.__shared_map.has(host.__actor_id)) {
            self.__shared_map.set(host.__actor_id, self.__shared_map.get(host.__actor_id)+1);
        } else {
            self.__shared_map.set(host.__actor_id, 1);
        }
    } else {
        self.__wait_queue.push_back({wait: host, state: 0});
        yield null;
    }
};

SharedMutex.prototype.try_lock_shared = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex try_lock_shared not in actor");
    if (0 != self.__shared_map.size || !self.__upgrade_mutex.__inside_id) {
        if (self.__shared_map.has(host.__actor_id)) {
            self.__shared_map.set(host.__actor_id, self.__shared_map.get(host.__actor_id)+1);
        } else {
            self.__shared_map.set(host.__actor_id, 1);
        }
        return true;
    }
    return false;
};

SharedMutex.prototype.yield_timed_lock_shared = function* (ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_timed_lock_shared not in actor");
    if (0 != self.__shared_map.size || !self.__upgrade_mutex.__inside_id) {
        if (self.__shared_map.has(host.__actor_id)) {
            self.__shared_map.set(host.__actor_id, self.__shared_map.get(host.__actor_id)+1);
        } else {
            self.__shared_map.set(host.__actor_id, 1);
        }
    } else {
        let node = self.__wait_queue.push_back({wait: host, state: 0});
        host.__timer_out(function () {
            self.__wait_queue.erase(node);
            host.__pull_yield(false);
        }, ms);
        return yield null;
    }
    return true;
};

SharedMutex.prototype.yield_lock_pess_shared = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_lock_pess_shared not in actor");
    if (self.__wait_queue.empty() && (0 != self.__shared_map.size || !self.__upgrade_mutex.__inside_id)) {
        if (self.__shared_map.has(host.__actor_id)) {
            self.__shared_map.set(host.__actor_id, self.__shared_map.get(host.__actor_id)+1);
        } else {
            self.__shared_map.set(host.__actor_id, 1);
        }
    } else {
        self.__wait_queue.push_back({wait: host, state: 0});
        yield null;
    }
};

SharedMutex.prototype.yield_lock_upgrade = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_lock_upgrade not in actor");
    yield* self.__upgrade_mutex.yield_lock();
};

SharedMutex.prototype.try_lock_upgrade = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex try_lock_upgrade not in actor");
    return self.__upgrade_mutex.try_lock();
};

SharedMutex.prototype.unlock = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex unlock not in actor");
    self.__upgrade_mutex.__inside_count--;
    if (0 == self.__upgrade_mutex.__inside_count && !self.__wait_queue.empty()) {
        let waitQueue = new MsgQueue();
        let ele = self.__wait_queue.front();
        self.__wait_queue.pop_front();
        waitQueue.push_back(ele.wait);
        if (0 == ele.state) {
            self.__upgrade_mutex.__inside_id = 0;
            self.__shared_map.set(ele.wait.__actor_id, 1);
            for (let it = self.__wait_queue.begin(); !self.__wait_queue.is_end(it);) {
                let ele = self.__wait_queue.element(it);
                if (0 == ele.state) {
                    self.__shared_map.set(ele.wait.__actor_id, 1);
                    waitQueue.push_back(ele.wait);
                    it = self.__wait_queue.next_erase(it);
                } else {
                    it = self.__wait_queue.next(it);
                }
            }
        } else {
            self.__upgrade_mutex.__inside_id = ele.wait.__actor_id;
            self.__upgrade_mutex.__inside_count++;
        }
        while (!waitQueue.empty()) {
            let wait = waitQueue.pop_front();
            if (wait.__timer_completed) {
                wait.__pull_yield();
            } else {
                wait.__cancel_timer();
                wait.__pull_yield(true);
            }
        }
    }
};

SharedMutex.prototype.unlock_upgrade = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex unlock_upgrade not in actor");
    self.__upgrade_mutex.unlock();
};

SharedMutex.prototype.unlock_shared = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex unlock_shared not in actor");
    let sc = self.__shared_map.get(host.__actor_id)-1;
    if (0 == sc) {
        self.__shared_map.delete(host.__actor_id);
        if (0 == self.__shared_map.size && !self.__wait_queue.empty()) {
            let waitQueue = new MsgQueue();
            let ele = self.__wait_queue.front();
            self.__wait_queue.pop_front();
            waitQueue.push_back(ele.wait);
            if (0 == ele.state) {
                self.__upgrade_mutex.__inside_id = 0;
                self.__shared_map.set(ele.wait.__actor_id, 1);
                for (let it = self.__wait_queue.begin(); !self.__wait_queue.is_end(it);) {
                    let ele = self.__wait_queue.element(it);
                    if (0 == ele.state) {
                        self.__shared_map.set(ele.wait.__actor_id, 1);
                        waitQueue.push_back(ele.wait);
                        it = self.__wait_queue.next_erase(it);
                    } else {
                        it = self.__wait_queue.next(it);
                    }
                }
            } else {
                self.__upgrade_mutex.__inside_id = ele.wait.__actor_id;
                self.__upgrade_mutex.__inside_count++;
            }
            while (!waitQueue.empty()) {
                let wait = waitQueue.pop_front();
                if (wait.__timer_completed) {
                    wait.__pull_yield();
                } else {
                    wait.__cancel_timer();
                    wait.__pull_yield(true);
                }
            }
        }
    } else {
        self.__shared_map.set(host.__actor_id, sc);
    }
};

SharedMutex.prototype.yield_unlock_and_lock_shared = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_unlock_and_lock_shared not in actor");
    self.unlock();
    yield* self.yield_lock_shared();
};

SharedMutex.prototype.yield_unlock_and_lock_upgrade = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_unlock_and_lock_upgrade not in actor");
    self.unlock();
    yield* self.yield_lock_shared();
    yield* self.yield_lock_upgrade();
};

SharedMutex.prototype.yield_unlock_upgrade_and_lock = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_unlock_upgrade_and_lock not in actor");
    self.unlock_upgrade();
    self.unlock_shared();
    yield* self.yield_lock();
};

SharedMutex.prototype.yield_unlock_shared_and_lock = function* () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("SharedMutex yield_unlock_shared_and_lock not in actor");
    self.unlock_shared();
    yield* self.yield_lock();
};
//----------------------------------------------------------------------------------------------------------------------
function ConditionVariable() {
    let self = this;
    self.__wait_queue = new List();
}

ConditionVariable.prototype.yield_wait = function* (mtx) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("ConditionVariable yield_wait not in actor");
    let inside = true;
    self.__wait_queue.push_back(function () {
        if (!inside) {
            host.__pull_yield();
        } else {
            inside = false;
        }
    });
    mtx.unlock();
    if (inside) {
        inside = false;
        yield null;
    }
    yield* mtx.yield_lock();
};

ConditionVariable.prototype.yield_timed_wait = function* (mtx, ms) {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("ConditionVariable yield_timed_wait not in actor");
    let inside = true;
    let overtime = false;
    let node = self.__wait_queue.push_back(function () {
        host.__cancel_timer();
        if (!inside) {
            host.__pull_yield();
        } else {
            inside = false;
        }
    });
    host.__timer_out(function () {
        overtime = true;
        self.__wait_queue.erase(node);
        if (!inside) {
            host.__pull_yield();
        } else {
            inside = false;
        }
    }, ms);
    mtx.unlock();
    if (inside) {
        inside = false;
        yield null;
    }
    yield* mtx.yield_lock();
    return !overtime;
};

ConditionVariable.prototype.notify_one = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("ConditionVariable notify_one not in actor");
    if (!self.__wait_queue.empty()) {
        self.__wait_queue.pop_front()();
    }
};

ConditionVariable.prototype.notify_all = function () {
    let self = this;
    let host = MyActor.self_actor();
    if (!host || !host.__in_actor)
        throw new Error("ConditionVariable notify_all not in actor");
    let tempQueue = new List();
    self.__wait_queue.swap(tempQueue);
    while (!tempQueue.empty()) {
        tempQueue.pop_front()();
    }
};
//----------------------------------------------------------------------------------------------------------------------
function MyActor(handler, quited_callback) {
    let self = this;
    self.__actor_id = ++global.__MyActor_actor_id;
    self.__is_run = false;
    self.__is_exited = false;
    self.__is_quited = false;
    self.__is_suspend = false;
    self.__is_force = false;
    self.__is_error = false;
    self.__in_actor = false;
    self.__context_count = 0;
    self.__parent_actor_id = -1;
    self.__timer_id = null;
    self.__timer_completed = true;
    self.__timer_start = 0;
    self.__timer_timeout = 0;
    self.__timer_end = 0;
    self.__timer_suspended = false;
    self.__timer_handler = null;
    self.__lock_quit = 0;
    self.__lock_suspend = 0;
    self.__hold_pull = false;
    self.__hold_quited = false;
    self.__hold_suspended = false;
    self.__wait_quit_msg = false;
    self.__quited_exec = [];
    self.__quited_notify = new MsgQueue();
    self.__suspend_queue = new MsgQueue();
    self.__error_notify = new MsgQueue();
    self.__msg_table = {};
    self.__child_map = new Map;
    self.__result = undefined;
    self.__temp_result = undefined;
    self.__top_handler = handler(self);
    self.__quited_callback = quited_callback;
    self.__handler_stack = new Stack();
}

MyActor.__msg_type_notify_handle = 0;
MyActor.__msg_type_trig_handle = 1;
MyActor.__msg_type_msg_handle = 2;
MyActor.__msg_type_csp_handle = 3;
MyActor.__msg_type_channel_handle = 4;
MyActor.__msg_type_quit_handle = 5;

MyActor.create = function (handler, quited_callback) {
    return new MyActor(handler, quited_callback);
};

MyActor.bind = function (handler, ...args) {
    return function (self) {
        return handler(self, ...args);
    };
};

MyActor.sleep = function (ms) {
    let self = global.__MyActor_self_actor;
    if (!self || !self.__in_actor)
        throw new Error("sleep not in actor");
    if (isNaN(ms))
        throw new Error("sleep number error");
    setTimeout(function () {
        self.__pull_yield();
    }, ms);
};

MyActor.tick = function () {
    return (new Date()).valueOf() - global.__MyActor_delta_stamp;
};

MyActor.time_string = function () {
    let fmt = (i)=>i>=10?i:"0"+i;
    let dt = new Date();
    return ""+dt.getFullYear()+"-"+fmt(1+dt.getMonth())+"-"+fmt(dt.getDate())+" "+fmt(dt.getHours())+":"+fmt(dt.getMinutes())+":"+fmt(dt.getSeconds());
};

MyActor.tick_string = function () {
    let fmt = (i)=>i>=10?i:"0"+i;
    let dt = new Date();
    let ms = dt.getMilliseconds();
    return ""+dt.getFullYear()+"-"+fmt(1+dt.getMonth())+"-"+fmt(dt.getDate())+" "+fmt(dt.getHours())+":"+fmt(dt.getMinutes())+":"+fmt(dt.getSeconds())+"."+(ms>=100?ms:(ms>=10?"0"+ms:"00"+ms));
};

MyActor.self_actor = function () {
    return global.__MyActor_self_actor;
};

MyActor.create_queue = function () {
    return new MsgQueue();
};

MyActor.create_stack = function () {
    return new Stack();
};

MyActor.create_list = function () {
    return new List();
};

MyActor.register_exception_handler = function (handler) {
    global.__MyActor_exception_handler = function (msg, err) {
        try {
            handler(msg, err);
        } catch (e) {
            console.log("register_exception_handler error");
        }
    }
};

MyActor.make_mutex = function () {
    return new Mutex();
};

MyActor.make_shared_mutex = function () {
    return new SharedMutex();
};

MyActor.make_condition_variable = function () {
    return new ConditionVariable();
};

MyActor.trace = function (...args) {
    for (let ele of args) {
        global.__MyActor_trace_buff += JSON.stringify(ele);
    }
};

MyActor.trace_flush = function (){
    console.log(global.__MyActor_trace_buff);
    global.__MyActor_trace_buff = "";
};

MyActor.trace_space = function (...args) {
    let msg = "";
    for (let i in args) {
        if (i < args.length-1) {
            msg += JSON.stringify(args[i]) + " ";
        } else {
            msg += JSON.stringify(args[i]);
        }
    }
    console.log(msg);
};

MyActor.trace_comma = function (...args) {
    let msg = "";
    for (let i in args) {
        if (i < args.length-1) {
            msg += JSON.stringify(args[i]) + ", ";
        } else {
            msg += JSON.stringify(args[i]);
        }
    }
    console.log(msg);
};

MyActor.wrap_tick = function (handler) {
    return function (...args) {
        process.nextTick(function () {
            handler(...args);
        });
    }
};

MyActor.wrap_tick_target = function (handler) {
    return function (...args) {
        let self = this;
        process.nextTick(function () {
            handler.call(self,...args);
        });
    }
};

MyActor.wrap_post = function (handler) {
    return function (...args) {
        setImmediate(function () {
            handler(...args);
        });
    }
};

MyActor.wrap_post_target = function (handler) {
    return function (...args) {
        let self = this;
        setImmediate(function () {
            handler.call(self,...args);
        });
    }
};

MyActor.wrap_hold_work = function (handler, cb) {
    MyActor.hold_work();
    let isInvoked = false;
    return function (...args) {
        if (isInvoked) {
            throw new Error("wrap_hold_work error");
        }
        isInvoked = true;
        let result = handler(...args);
        MyActor.release_work(cb);
        return result;
    }
};

MyActor.hold_work = function (holdNum) {
    if (undefined === holdNum) {
        holdNum = 1;
    } else if (holdNum <= 0) {
        throw new Error("hold_work error");
    }
    if (0 == global.__MyActor_hold_count) {
        global.__MyActor_hold_id = setInterval(()=>{}, 0x7FFFFFFF);
    }
    global.__MyActor_hold_count += holdNum;
};

MyActor.release_work = function (cb) {
    if (global.__MyActor_hold_count <= 0) {
        throw new Error("release_work error");
    }
    global.__MyActor_hold_count--;
    if (0 == global.__MyActor_hold_count) {
        clearInterval(global.__MyActor_hold_id);
        global.__MyActor_hold_id = undefined;
        if (cb) {
            MyActor.check_exception_callback("release_work callback error", cb);
        }
    }
};

MyActor.force_trace_error_stack = function () {
    global.__MyActor_trace_error_stack = true;
};

MyActor.enable_source_map_trace = function () {
    try {
        require("source-map-support").install();
    } catch (err) {
        global.__MyActor_exception_handler("enable_source_map_trace error", err);
    }
};

MyActor.check_exception_callback = function (msg, handler) {
    try {
        handler();
    } catch (err) {
        MyActor.__MyActor_exception_handler(msg, err);
    }
};

MyActor.prototype.make_mutex = MyActor.make_mutex;
MyActor.prototype.make_shared_mutex = MyActor.make_shared_mutex;
MyActor.prototype.make_condition_variable = MyActor.make_condition_variable;

MyActor.prototype.self_id = function () {
    let self = this;
    return self.__actor_id;
};

MyActor.prototype.result = function () {
    let self = this;
    if (!self.__is_exited)
        throw new Error("get result error");
    return self.__result;
};

MyActor.prototype.create_child = function (handler, cb) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("create_child not in actor");
    let child = new MyActor(handler, function (result) {
        if (cb) {
            MyActor.check_exception_callback("create_child callback error", ()=> cb(result));
        }
        self.__child_quited_handler(child);
    });
    child.__parent_actor_id = self.__actor_id;
    self.__child_map.set(child.__actor_id, child);
    return child;
};

MyActor.prototype.run = function () {
    let self = this;
    if (!self.__is_quited && !self.__is_run) {
        self.__is_run = true;
        self.__pull_yield();
    }
    return self;
};

MyActor.prototype.force_quit = function (cb) {
    let self = this;
    setImmediate(function () {
        if (!self.__is_quited) {
            if (cb) {
                self.__quited_notify.push_back(cb);
            }
            if (!self.__lock_quit) {
                self.__is_force = true;
                self.__is_quited = true;
                self.__is_suspend = false;
                self.__lock_suspend = 0;
                self.__hold_pull = false;
                self.__hold_suspended = false;
                self.__cancel_timer();
                if (self.__child_map.size) {
                    self.__child_map.forEach((child, id)=> child.force_quit());
                } else {
                    self.__quited_to_do();
                }
            } else {
                self.__hold_quited = true;
                if (self.__wait_quit_msg) {
                    self.__wait_quit_msg = false;
                    self.__pull_yield();
                }
            }
        } else if (cb) {
            if (self.__is_exited) {
                MyActor.check_exception_callback("force_quit callback error", cb);
            } else {
                self.__quited_notify.push_back(cb);
            }
        }
    });
};

MyActor.prototype.children_force_quit = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("children_force_quit not in actor");
    self.__child_map.forEach((child, id)=> child.force_quit());
};

MyActor.prototype.is_start = function () {
    let self = this;
    return self.__is_run;
};

MyActor.prototype.is_exited = function () {
    let self = this;
    return self.__is_exited;
};

MyActor.prototype.is_force = function () {
    let self = this;
    if (!self.__is_exited)
        throw new Error("is_force error");
    return self.__is_force;
};

MyActor.prototype.is_error = function () {
    let self = this;
    if (!self.__is_exited)
        throw new Error("is_error error");
    return self.__is_error;
};

MyActor.prototype.has_quit_msg = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("has_quit_msg not in actor");
    return self.__hold_quited;
};

MyActor.prototype.yield_suspend = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_suspend not in actor");
    let count = otherActors.length;
    if (count) {
        let inside = true;
        for (let ele of otherActors) {
            ele.__notify_suspend(function () {
                count--;
                if (0 == count) {
                    if (!inside) {
                        self.__pull_yield();
                    } else {
                        inside = false;
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_resume = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_resume not in actor");
    let count = otherActors.length;
    if (count) {
        let inside = true;
        for (let ele of otherActors) {
            ele.__notify_resume(function () {
                count--;
                if (0 == count) {
                    if (!inside) {
                        self.__pull_yield();
                    } else {
                        inside = false;
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.suspend = function (cb) {
    let self = this;
    setImmediate(function () {
        self.__notify_suspend(function () {
            if (cb) {
                MyActor.check_exception_callback("suspend callback error", cb);
            }
        });
    });
};

MyActor.prototype.resume = function (cb) {
    let self = this;
    setImmediate(function () {
        self.__notify_resume(function () {
            if (cb) {
                MyActor.check_exception_callback("resume callback error", cb);
            }
        });
    });
};

MyActor.prototype.yield_children_suspend = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_suspend not in actor");
    let count = self.__child_map.size;
    if (count) {
        let inside = true;
        self.__child_map.forEach(function(child, id) {
            child.__notify_suspend(function () {
                count--;
                if (0 == count) {
                    if (!inside) {
                        self.__pull_yield();
                    } else {
                        inside = false;
                    }
                }
            })
        });
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_children_resume = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_resume not in actor");
    let count = self.__child_map.size;
    if (count) {
        let inside = true;
        self.__child_map.forEach((child, id)=> child.__notify_resume(function () {
            count--;
            if (0 == count) {
                if (!inside) {
                    self.__pull_yield();
                } else {
                    inside = false;
                }
            }
        }));
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_safe_suspend = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_suspend not in actor");
    self.lock_quit();
    yield* self.yield_suspend(...otherActors);
    yield* self.yield_unlock_quit();
};

MyActor.prototype.yield_safe_resume = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_resume not in actor");
    self.lock_quit();
    yield* self.yield_resume(...otherActors);
    yield* self.yield_unlock_quit();
};

MyActor.prototype.yield_safe_children_suspend = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_children_suspend not in actor");
    self.lock_quit();
    yield* self.yield_children_suspend();
    yield* self.yield_unlock_quit();
};

MyActor.prototype.yield_safe_children_resume = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_children_resume not in actor");
    self.lock_quit();
    yield* self.yield_children_resume();
    yield* self.yield_unlock_quit();
};

MyActor.prototype.lock_suspend = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("lock_suspend not in actor");
    self.__lock_suspend++;
};

MyActor.prototype.yield_unlock_suspend = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_unlock_suspend not in actor");
    if (0 == self.__lock_suspend)
        throw new Error("yield_unlock_suspend error");
    self.__lock_suspend--;
    if (!self.__lock_suspend && self.__hold_suspended) {
        self.__hold_suspended = false;
        if (self.__suspend_queue.front().is_suspend) {
            self.__suspend();
        } else {
            self.__resume();
        }
        self.__post_pull();
        yield null;
    }
};

MyActor.prototype.yield_force_quit = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_force_quit not in actor");
    let count = otherActors.length;
    if (count) {
        for (let ele of otherActors) {
            ele.force_quit(function () {
                count--;
                if (0 == count) {
                    self.__pull_yield();
                }
            });
        }
        yield null;
    }
};

MyActor.prototype.yield_children_force_quit = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_force_quit not in actor");
    let count = self.__child_map.size;
    if (count) {
        self.__child_map.forEach((child, id)=> child.force_quit(function () {
            count--;
            if (0 == count) {
                self.__pull_yield();
            }
        }));
        yield null;
    }
};

MyActor.prototype.yield_safe_force_quit = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_force_quit not in actor");
    self.lock_quit();
    yield* self.yield_force_quit(...otherActors);
    yield* self.yield_unlock_quit();
};

MyActor.prototype.yield_safe_children_force_quit = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_safe_children_force_quit not in actor");
    self.lock_quit();
    yield* self.yield_children_force_quit();
    yield* self.yield_unlock_quit();
};

MyActor.prototype.lock_quit = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("lock_quit not in actor");
    self.__lock_quit++;
};

MyActor.prototype.yield_unlock_quit = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_unlock_quit not in actor");
    if (!self.__lock_quit)
        throw new Error("yield_unlock_quit error");
    self.__lock_quit--;
    if (0 == self.__lock_quit && self.__hold_quited) {
        self.force_quit();
        yield null;
    }
};

MyActor.prototype.append_quited_notify = function (cb) {
    let self = this;
    if (self.__is_exited) {
        MyActor.check_exception_callback("append_quited_notify callback error", cb);
    } else {
        self.__quited_notify.push_back(cb);
    }
};

MyActor.prototype.append_quited_exec = function (handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_unlock_quit not in actor");
    self.__quited_exec.push(handler);
};

MyActor.prototype.append_error_notify = function (cb) {
    let self = this;
    if (self.__is_exited) {
        if (self.__is_error) {
            MyActor.check_exception_callback("append_error_notify callback error", cb);
        }
    } else {
        self.__error_notify.push_back(cb);
    }
};

MyActor.prototype.yield_wait_quit = function* (...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_quit not in actor");
    let count = otherActors.length;
    if (count) {
        let inside = true;
        for (let ele of otherActors) {
            ele.append_quited_notify(function () {
                count--;
                if (0 == count) {
                    if (!inside) {
                        self.__pull_yield();
                    } else {
                        inside = false;
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_wait_once_quit = function* (... otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_once_quit not in actor");
    if (otherActors.length) {
        let inside = true;
        let returned = false;
        let result = null;
        for (let ele of otherActors) {
            ele.append_quited_notify(function () {
                if (!returned) {
                    returned = true;
                    if (!inside) {
                        self.__pull_yield(ele);
                    } else {
                        inside = false;
                        result = ele;
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            return yield null;
        }
        return result;
    }
};

MyActor.prototype.yield_timed_wait_quit = function* (ms, ...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_timed_wait_quit not in actor");
    let count = otherActors.length;
    if (count) {
        let inside = true;
        let timeout = false;
        let result = null;
        for (let ele of otherActors) {
            ele.append_quited_notify(function () {
                count--;
                if (0 == count && !timeout) {
                    if (!inside) {
                        self.__pull_yield(true);
                    } else {
                        inside = false;
                        result = true;
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            self.__timer_out(function () {
                timeout = true;
                self.__pull_yield(false);
            }, ms);
            return yield null;
        }
        return result;
    }
    return true;
};

MyActor.prototype.yield_timed_wait_once_quit = function* (ms, ...otherActors) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_timed_wait_once_quit not in actor");
    if (otherActors.length) {
        let inside = true;
        let returned = false;
        let result = null;
        for (let ele of otherActors) {
            ele.append_quited_notify(function () {
                if (!returned) {
                    returned = true;
                    if (!inside) {
                        self.__pull_yield({ok: true, value: ele});
                    } else {
                        inside = false;
                        result = {ok: true, value: ele};
                    }
                }
            });
        }
        if (inside) {
            inside = false;
            self.__timer_out(function () {
                returned = true;
                self.__pull_yield({ok: false});
            }, ms);
            return yield null;
        }
        return result;
    }
    return {ok: true};
};

MyActor.prototype.yield_children_wait_quit = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_wait_quit not in actor");
    let count = self.__child_map.size;
    if (count) {
        let inside = true;
        self.__child_map.forEach((child, id)=> child.append_quited_notify(function () {
            count--;
            if (0 == count) {
                if (!inside) {
                    self.__pull_yield();
                } else {
                    inside = false;
                }
            }
        }));
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_children_wait_once_quit = function* () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_wait_once_quit not in actor");
    if (self.__child_map.size) {
        let inside = true;
        let returned = false;
        self.__child_map.forEach((child, id)=> child.append_quited_notify(function () {
            if (!returned) {
                returned = true;
                if (!inside) {
                    self.__pull_yield();
                } else {
                    inside = false;
                }
            }
        }));
        if (inside) {
            inside = false;
            yield null;
        }
    }
};

MyActor.prototype.yield_children_timed_wait_quit = function* (ms) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_timed_wait_quit not in actor");
    let count = self.__child_map.size;
    if (count) {
        let inside = true;
        let timeout = false;
        let result = null;
        self.__child_map.forEach((child, id)=> child.append_quited_notify(function () {
            count--;
            if (0 == count && !timeout) {
                if (!inside) {
                    self.__pull_yield(true);
                } else {
                    inside = false;
                    result = true;
                }
            }
        }));
        if (inside) {
            inside = false;
            self.__timer_out(function () {
                timeout = true;
                self.__pull_yield(false);
            }, ms);
            return yield null;
        }
        return result;
    }
    return true;
};

MyActor.prototype.yield_children_timed_wait_once_quit = function* (ms) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_children_timed_wait_once_quit not in actor");
    if (self.__child_map.size) {
        let inside = true;
        let returned = false;
        let result = null;
        self.__child_map.forEach((child, id)=> child.append_quited_notify(function () {
            if (!returned) {
                returned = true;
                if (!inside) {
                    self.__pull_yield({ok: true, value: child});
                } else {
                    inside = false;
                    result = {ok: true, value: child};
                }
            }
        }));
        if (inside) {
            inside = false;
            self.__timer_out(function () {
                returned = true;
                self.__pull_yield({ok: false});
            }, ms);
            return yield null;
        }
        return result;
    }
    return {ok: true};
};

MyActor.prototype.yield_wait_quit_result = function* (otherActor) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_quit_result not in actor");
    yield* self.yield_wait_quit(otherActor);
    if (otherActor.is_error()) {
        throw otherActor.result();
    }
    return otherActor.result();
};

MyActor.prototype.yield_sleep = function (ms) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_sleep not in actor");
    self.__timer_out(function () {
        self.__pull_yield();
    }, ms);
};

MyActor.prototype.yield_tick = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_tick not in actor");
    self.__post_pull();
};

MyActor.prototype.make_notify_handle = function () {
    let self = this;
    let handle = {
        __type: MyActor.__msg_type_notify_handle,
        __msg_queue: new MsgQueue(),
        __is_wait: false,
        __closed: false,
        __actor_id: self.__actor_id,
        __warning_length: 0x7FFFFFFF,
        __warning_handler: undefined
    };
    self.__quited_exec.push(function () {
        handle.__closed = true;
        handle.__warning_handler = undefined;
        while (!handle.__msg_queue.empty()) {
            let msg = handle.__msg_queue.pop_front();
            if (msg.reply) {
                MyActor.check_exception_callback("notify reply error", ()=> msg.reply(undefined, {err: "not processed"}));
            }
        }
    });
    return handle;
};

MyActor.prototype.make_multi_notify_handle = function (num) {
    let self = this;
    if (isNaN(num) || num > 10) {
        throw new Error("make_multi_notify_handle error");
    }
    let result = [];
    for (let i = 0; i < num; i++) {
        result[i] = self.make_notify_handle();
    }
    return result;
};

MyActor.prototype.notify_msg_number = function (handle) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("notify_msg_number not in actor");
    return handle.__msg_queue.length();
};

MyActor.prototype.notify_msg_warning = function (handle, num, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("notify_msg_warning not in actor");
    handle.__warning_length = num;
    if (handler) {
        handle.__warning_handler = handler;
    } else {
        handle.__warning_handler = function () {
            throw new Error("notify msg is too much");
        };
    }
};

MyActor.prototype.make_notify = function (handle) {
    let self = this;
    return self.make_notify_translate(handle);
};

MyActor.prototype.make_notify_translate = function (handle, translator) {
    let self = this;
    return function (...args) {
        if (translator) {
            args = translator(...args);
        }
        let [msg, reply] = args;
        if (!handle.__is_quited) {
            if (!handle.__closed) {
                if (handle.__is_wait) {
                    handle.__is_wait = false;
                    if (self.__timer_completed) {
                        self.__pull_yield({value: msg, reply: reply});
                    } else {
                        self.__cancel_timer();
                        self.__pull_yield({ok: true, value: msg, reply: reply});
                    }
                } else {
                    handle.__msg_queue.push_back({value: msg, reply: reply});
                    if (handle.__msg_queue.length() > handle.__warning_length) {
                        MyActor.check_exception_callback("notify warning error", ()=> handle.__warning_handler());
                    }
                }
            } else if (reply) {
                MyActor.check_exception_callback("notify reply error", ()=> reply(undefined, {err: "not receive"}));
            }
        } else {
            if (!handle.__is_exited) {
                handle.__msg_queue.push_back({value: msg, reply: reply});
            } else if (reply) {
                MyActor.check_exception_callback("notify reply error", ()=> reply(undefined, {err: "not receive"}));
            }
        }
    }
};

MyActor.prototype.yield_wait_notify = function* (handle) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_notify not in actor");
    if (handle.__actor_id != self.__actor_id)
        throw new Error("yield_wait_notify is not current actor");
    if (handle.__msg_queue.empty()) {
        handle.__is_wait = true;
        return yield null;
    }
    return handle.__msg_queue.pop_front();
};

MyActor.prototype.yield_wait_many_notify = function* (handle, num) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_many_notify not in actor");
    if (handle.__actor_id != self.__actor_id)
        throw new Error("yield_wait_many_notify is not current actor");
    let result = [];
    while (num-- > 0) {
        if (handle.__msg_queue.empty()) {
            handle.__is_wait = true;
            result.push(yield null);
        } else {
            result.push(handle.__msg_queue.pop_front());
        }
    }
    return result;
};

MyActor.prototype.yield_timed_wait_notify = function* (ms, handle) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_timed_wait_notify not in actor");
    if (handle.__actor_id != self.__actor_id)
        throw new Error("yield_timed_wait_notify is not current actor");
    if (handle.__msg_queue.empty()) {
        handle.__is_wait = true;
        self.__timer_out(function () {
            handle.__is_wait = false;
            self.__pull_yield({ok: false});
        }, ms);
        return yield null;
    }
    let msg = handle.__msg_queue.pop_front();
    return {ok: true, value: msg.value, reply: msg.reply};
};

MyActor.prototype.close_notify_handle = function (...handles) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("close_notify_handle not in actor");
    for (let handle of handles) {
        if (handle.__actor_id != self.__actor_id)
            throw new Error("close_notify_handle is not current actor");
        handle.__closed = true;
        handle.__warning_handler = undefined;
        while (!handle.__msg_queue.empty()) {
            let msg = handle.__msg_queue.pop_front();
            if (msg.reply) {
                MyActor.check_exception_callback("notify reply error", ()=> msg.reply(undefined, {err: "not processed"}));
            }
        }
    }
};

MyActor.prototype.close_trig_handle = function (...handles) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("close_trig_handle not in actor");
    for (let handle of handles) {
        if (handle.__actor_id != self.__actor_id)
            throw new Error("close_trig_handle is not current actor");
        handle.__closed = true;
        if (handle.__has_msg) {
            handle.__has_msg = false;
            if (handle.__msg.reply) {
                MyActor.check_exception_callback("trig reply error", ()=> handle.__msg.reply(undefined, {err: "not processed"}));
                handle.__msg = undefined;
            }
        }
    }
};

MyActor.prototype.is_handle_closed = function (handle) {
    return handle.__closed;
};

MyActor.prototype.make_trig_handle = function () {
    let self = this;
    let handle = {
        __type: MyActor.__msg_type_trig_handle,
        __msg: undefined,
        __is_triged: false,
        __is_wait: false,
        __closed: false,
        __has_msg: false,
        __actor_id: self.__actor_id
    };
    self.__quited_exec.push(function () {
        handle.__closed = true;
        if (handle.__has_msg) {
            handle.__has_msg = false;
            if (handle.__msg.reply) {
                MyActor.check_exception_callback("trig reply error", ()=> handle.__msg.reply(undefined, {err: "not processed"}));
                handle.__msg = undefined;
            }
        }
    });
    return handle;
};

MyActor.prototype.make_multi_trig_handle = function (num) {
    let self = this;
    if (isNaN(num) || num > 10) {
        throw new Error("make_multi_trig_handle error");
    }
    let result = [];
    for (let i = 0; i < num; i++) {
        result[i] = self.make_trig_handle();
    }
    return result;
};

MyActor.prototype.make_trig = function (handle) {
    let self = this;
    return self.make_trig_translate(handle);
};

MyActor.prototype.make_trig_translate = function (handle, translator) {
    let self = this;
    return function (...args) {
        if (translator) {
            args = translator(...args);
        }
        let [msg, reply] = args;
        if (!self.__is_quited) {
            if (!handle.__is_triged && !handle.__closed) {
                handle.__is_triged = true;
                if (handle.__is_wait) {
                    handle.__is_wait = false;
                    if (self.__timer_completed) {
                        self.__pull_yield({value: msg, reply: reply});
                    } else {
                        self.__cancel_timer();
                        self.__pull_yield({ok: true, value: msg, reply: reply});
                    }
                } else {
                    handle.__has_msg = true;
                    handle.__msg = {value: msg, reply: reply};
                }
            } else if (reply) {
                MyActor.check_exception_callback("trig reply error", ()=> reply(undefined, {err: "not receive"}));
            }
        } else {
            if (!self.__is_exited && !handle.__is_triged) {
                handle.__has_msg = true;
                handle.__msg = {value: msg, reply: reply};
            } else if (reply) {
                MyActor.check_exception_callback("trig reply error", ()=> reply(undefined, {err: "not receive"}));
            }
        }
    }
};

MyActor.prototype.yield_wait_trig = function* (handle) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_trig not in actor");
    if (handle.__actor_id != self.__actor_id)
        throw new Error("yield_wait_trig is not current actor");
    if (!handle.__has_msg) {
        handle.__is_wait = true;
        return yield null;
    }
    handle.__has_msg = false;
    let msg = handle.__msg;
    handle.__msg = undefined;
    return msg;
};

MyActor.prototype.yield_timed_wait_trig = function* (ms, handle) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_timed_wait_trig not in actor");
    if (handle.__actor_id != self.__actor_id)
        throw new Error("yield_timed_wait_trig is not current actor");
    if (!handle.__has_msg) {
        handle.__is_wait = true;
        self.__timer_out(function () {
            handle.__is_wait = false;
            self.__pull_yield({ok: false});
        }, ms);
        return yield null;
    }
    handle.__has_msg = false;
    return {ok: true, value: handle.__msg.value, reply: handle.__msg.reply};
};

MyActor.prototype.get_msg_handle = function (id) {
    let self = this;
    return self.__msg_handle(id);
};

MyActor.prototype.get_quit_handle = function () {
    return {__type: MyActor.__msg_type_quit_handle, __optioned: false};
};

MyActor.prototype.msg_number = function (id) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("msg_number not in actor");
    return self.__msg_handle(id).__msg_state.__msg_queue.length();
};

MyActor.prototype.post_msg = function (id, msg, reply) {
    let self = this;
    self.make_msg_notify(id)(msg, reply);
};

MyActor.prototype.yield_send_msg = function* (otherActor, id, msg) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_send_msg not in actor");
    let inside = true;
    let result = null;
    otherActor.post_msg(id, msg, function (...args) {
        if (!inside) {
            self.__pull_yield(args);
        } else {
            inside = false;
            result = args;
        }
    });
    if (inside) {
        inside = false;
        return yield null;
    }
    return result;
};

MyActor.prototype.make_channel_handle = function (maxLength = 0) {
    return new Channel(maxLength);
};

MyActor.prototype.yield_channel_push = function (handle, msg) {
    return handle.yield_push(msg);
};

MyActor.prototype.yield_channel_try_push = function (handle, msg) {
    return handle.yield_try_push(msg);
};

MyActor.prototype.yield_channel_timed_push = function (handle, ms, msg) {
    return handle.yield_timed_push(ms, msg);
};

MyActor.prototype.yield_channel_pop = function (handle) {
    return handle.yield_pop();
};

MyActor.prototype.yield_channel_try_pop = function (handle) {
    return handle.yield_try_pop();
};

MyActor.prototype.yield_channel_timed_pop = function (handle, ms) {
    return handle.yield_timed_pop(ms);
};

MyActor.prototype.make_csp_handle = function() {
    return new Csp();
};

MyActor.prototype.yield_csp_invoke = function (handle, ...args) {
    return handle.yield_invoke(...args);
};

MyActor.prototype.yield_timed_csp_invoke = function (ms, handle, ...args) {
    return handle.yield_timed_invoke(ms, ...args);
};

MyActor.prototype.yield_try_csp_invoke = function (handle, ...args) {
    return handle.yield_try_invoke(...args);
};

MyActor.prototype.yield_wait_csp = function (handle, handler) {
    return handle.yield_wait(handler);
};

MyActor.prototype.yield_timed_wait_csp = function (ms, handle, handler) {
    return handle.yield_timed_wait(ms, handler);
};

MyActor.prototype.yield_try_wait_csp = function (handle, handler) {
    return handle.yield_try_wait(handler);
};

MyActor.prototype.make_msg_notify = function (id) {
    let self = this;
    let msg_handle = self.__msg_handle(id);
    return function (msg, reply) {
        let ele = msg_handle;
        if (!self.__is_quited) {
            if (!ele.__msg_state.__is_wait) {
                ele.__msg_state.__msg_queue.push_back({value: msg, reply: reply});
            } else {
                ele.__msg_state.__is_wait = false;
                let processActor;
                do {
                    processActor = ele.__ext_actor;
                    ele = ele.__agent_handle;
                } while (ele);
                if (processActor) {
                    if (processActor.__timer_completed) {
                        processActor.__pull_yield({value: msg, reply: reply});
                    } else {
                        processActor.__cancel_timer();
                        processActor.__pull_yield({ok: true, value: msg, reply: reply})
                    }
                }
            }
        } else {
            if (self.__is_exited) {
                if (ele.__root_id != self.__root_id) {
                    ele.__msg_state.__msg_queue.push_back({value: msg, reply: reply});
                } else if (reply) {
                    MyActor.check_exception_callback("msg reply error", ()=> reply(undefined, {err: "not receive"}));
                }
            } else {
                ele.__msg_state.__msg_queue.push_back({value: msg, reply: reply});
            }
        }
    }
};

MyActor.prototype.make_msg_sender = function (id) {
    let self = this;
    let notify = self.make_msg_notify(id);
    return function* (msg) {
        let host = MyActor.self_actor();
        if (!host.__in_actor)
            throw new Error("msg_sender not in actor");
        let inside = true;
        let result = null;
        notify(msg, function (...reply) {
            if (!inside) {
                host.__pull_yield(reply);
            } else {
                inside = false;
                result = reply;
            }
        });
        if (inside) {
            inside = false;
            return yield null;
        }
        return result;
    };
};

MyActor.prototype.msg_agent_to = function (id, childActor) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("msg_agent_to not in actor");
    if (childActor.__parent_actor_id != self.__actor_id)
        throw new Error("msg_agent_to error");
    if (childActor.__is_quited)
        return false;
    let ele = self.__msg_handle(id);
    if (ele.__agent_handle && ele.__agent_handle.__ext_actor && ele.__agent_handle.__ext_actor.__actor_id == childActor.__actor_id)
        return false;
    if (ele.__agent_handle)
        self.cancel_msg_agent(id);
    let eleit = childActor.__msg_handle(id);
    let eleStateBak = eleit.__msg_state;
    do {
        eleit.__msg_state = ele.__msg_state;
        eleit.__root_id = ele.__root_id;
        ele.__agent_handle = eleit;
        ele = eleit;
        eleit = eleit.__agent_handle;
    } while (eleit);
    if (eleStateBak.__is_wait) {
        eleStateBak.__is_wait = false;
        if (!ele.__is_quited) {
            if (ele.__msg_state.__msg_queue.empty()) {
                ele.__msg_state.__is_wait = true;
            } else {
                if (ele.__ext_actor.__timer_completed) {
                    ele.__ext_actor.__pull_yield(ele.__msg_state.__msg_queue.pop_front());
                } else {
                    ele.__ext_actor.__cancel_timer();
                    let msg = ele.__msg_state.__msg_queue.pop_front();
                    ele.__ext_actor.__pull_yield({ok: true, value: msg.value, reply: msg.reply});
                }
            }
        }
    }
    return true;
};

MyActor.prototype.cancel_msg_agent = function (id) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("cancel_msg_agent not in actor");
    let ele = self.__msg_handle(id);
    let eleit = ele.__agent_handle;
    ele.__agent_handle = null;
    if (eleit && eleit.__ext_actor) {
        let rootId = eleit.__ext_actor.__actor_id;
        let newState = {
            __msg_queue: new MsgQueue(),
            __is_wait: ele.__msg_state.__is_wait
        };
        do {
            eleit.__msg_state.__is_wait = false;
            eleit.__msg_state = newState;
            eleit.__root_id = rootId;
            eleit = eleit.__agent_handle;
        } while (eleit);
    }
};

MyActor.prototype.yield_wait_msg = function* (id) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_msg not in actor");
    let ele = self.__msg_handle(id);
    if (ele.__agent_handle)
        self.cancel_msg_agent(id);
    if (ele.__msg_state.__msg_queue.empty()) {
        ele.__msg_state.__is_wait = true;
        return yield null;
    }
    return ele.__msg_state.__msg_queue.pop_front();
};

MyActor.prototype.yield_wait_many_msg = function* (id, num) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_wait_many_msg not in actor");
    let ele = self.__msg_handle(id);
    if (ele.__agent_handle)
        self.cancel_msg_agent(id);
    let result = [];
    while (num-- > 0) {
        if (ele.__msg_state.__msg_queue.empty()) {
            ele.__msg_state.__is_wait = true;
            result.push(yield null);
        } else {
            result.push(ele.__msg_state.__msg_queue.pop_front());
        }
    }
    return result;
};

MyActor.prototype.yield_timed_wait_msg = function* (ms, id) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_timed_wait_msg not in actor");
    let ele = self.__msg_handle(id);
    if (ele.__agent_handle)
        self.cancel_msg_agent(id);
    if (ele.__msg_state.__msg_queue.empty()) {
        ele.__msg_state.__is_wait = true;
        self.__timer_out(function () {
            ele.__msg_state.__is_wait = false;
            self.__pull_yield({ok: false});
        }, ms);
        return yield null;
    }
    let msg = ele.__msg_state.__msg_queue.pop_front();
    return {ok: true, value: msg.value, reply: msg.reply};
};

MyActor.prototype.yield_select_msg = function* (...args) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_select_msg not in actor");
    for (let i = 0; i < args.length; i+=2) {
        if (undefined === args[i].__type) {
            throw new Error("yield_select_msg param is error");
        }
        if (args[i].__type == MyActor.__msg_type_channel_handle) {
            args[i] = {__type: MyActor.__msg_type_channel_handle, channel: args[i], ntfSign: {__ntf_sign: true, __effect: false}};
        }
    }
    let cspNode;
    let setHandleWait = function (handle, is_wait) {
        switch (handle.__type) {
            case MyActor.__msg_type_notify_handle: handle.__is_wait = is_wait; break;
            case MyActor.__msg_type_trig_handle: handle.__is_wait = is_wait; break;
            case MyActor.__msg_type_msg_handle: handle.__msg_state.__is_wait = is_wait; break;
            case MyActor.__msg_type_csp_handle:
                if (is_wait) {
                    cspNode = handle.__receiver_queue.push_back(self);
                } else if (!handle.__receiver_queue.is_invalid(cspNode)) {
                    handle.__receiver_queue.erase(cspNode);
                }
                break;
            case MyActor.__msg_type_channel_handle:
                if (is_wait) {
                    handle.channel.append_pop_notify(function (state) {
                        handle.channel.try_pop((state, msg)=> self.__pull_yield([state, msg]));
                    }, handle.ntfSign);
                } else {
                    handle.channel.remove_pop_notify(handle.ntfSign);
                }
                break;
            case MyActor.__msg_type_quit_handle: self.__wait_quit_msg = handle.__optioned ? false : is_wait; break;
        }
    };
    let getHandleIsWait = function (handle) {
        switch (handle.__type) {
            case MyActor.__msg_type_notify_handle: return handle.__is_wait;
            case MyActor.__msg_type_trig_handle: return handle.__is_wait;
            case MyActor.__msg_type_msg_handle: return handle.__msg_state.__is_wait;
            case MyActor.__msg_type_csp_handle: return !handle.__receiver_queue.is_invalid(cspNode);
            case MyActor.__msg_type_channel_handle: return !handle.ntfSign.__ntf_sign;
            case MyActor.__msg_type_quit_handle:
                let res = handle.__optioned ? true : self.__wait_quit_msg;
                if (!res) {
                    handle.__optioned = true;
                }
                return res;
        }
    };
    let handleInvoke = function(handle, handler, msg) {
        switch (handle.__type) {
            case MyActor.__msg_type_notify_handle: return handler(msg);
            case MyActor.__msg_type_trig_handle: return handler(msg);
            case MyActor.__msg_type_msg_handle: return handler(msg);
            case MyActor.__msg_type_csp_handle: return handler(msg[0], msg[1]);
            case MyActor.__msg_type_channel_handle: return handler(msg[0], msg[1]);
            case MyActor.__msg_type_quit_handle: return handler();
        }
    };
    let stop = false;
    do {
        let runOnce = false;
        for (let i = 0; i < args.length && !runOnce && !stop; i+=2) {
            let handle = args[i];
            try {
                switch (handle.__type) {
                    case MyActor.__msg_type_notify_handle:
                        if (!handle.__msg_queue.empty()) {
                            runOnce = true;
                            stop = yield* handleInvoke(handle, args[i + 1], handle.__msg_queue.pop_front());
                        }
                        break;
                    case MyActor.__msg_type_trig_handle:
                        if (handle.__has_msg) {
                            runOnce = true;
                            handle.__has_msg = false;
                            handle.__is_triged = true;
                            let msg = handle.__msg;
                            handle.__msg = undefined;
                            stop = yield* handleInvoke(handle, args[i + 1], msg);
                        }
                        break;
                    case MyActor.__msg_type_msg_handle:
                        if (!handle.__msg_state.__msg_queue.empty()) {
                            runOnce = true;
                            stop = yield* handleInvoke(handle, args[i + 1], handle.__msg_state.__msg_queue.pop_front());
                        }
                        break;
                    case MyActor.__msg_type_csp_handle:
                        if (!handle.__sender_queue.empty()) {
                            runOnce = true;
                            let [src, reply, msg] = handle.__sender_queue.pop_front();
                            src.__cancel_timer();
                            stop = yield* handleInvoke(handle, args[i + 1], [reply, msg]);
                        }
                        break;
                    case MyActor.__msg_type_channel_handle:
                        if (handle.channel.__has_msg()) {
                            runOnce = true;
                            let result = null;
                            handle.channel.try_pop((state, msg)=> result = [state, msg]);
                            stop = yield* handleInvoke(handle, args[i + 1], result);
                        }
                        break;
                    case MyActor.__msg_type_quit_handle:
                        if (self.__hold_quited && !handle.__optioned) {
                            handle.__optioned = true;
                            stop = yield* handleInvoke(handle, args[i + 1]);
                        }
                        break;
                }
            } catch (err) {
                global.__MyActor_exception_handler("select msg handler exception", err);
            }
        }
        if (!runOnce) {
            for (let i = 0; i < args.length; i+=2) {
                setHandleWait(args[i], true);
            }
            let msg = yield null;
            for (let i = 0; i < args.length; i+=2) {
                if (!getHandleIsWait(args[i])) {
                    let ti = i;
                    for (i+=2; i < args.length; i+=2) {
                        setHandleWait(args[i], false);
                    }
                    try {
                        stop = yield* handleInvoke(args[ti], args[ti + 1], msg);
                    } catch(err) {
                        global.__MyActor_exception_handler("select msg handler exception", err);
                    }
                    break;
                } else {
                    setHandleWait(args[i], false);
                }
            }
        }
    } while (!stop);
};

MyActor.prototype.delay_trig = function (ms, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("delay_trig not in actor");
    self.__timer_out(handler, ms);
};

MyActor.prototype.cancel_delay_trig = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("cancel_delay_trig not in actor");
    self.__cancel_timer();
};

MyActor.prototype.make_context = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_context not in actor");
    let contextId = self.__context_count;
    return function (arg) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            self.__post_pull(arg);
        } else {
            throw new Error("make_context repeat callback");
        }
    };
};

MyActor.prototype.make_asio_context = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_asio_context not in actor");
    let contextId = self.__context_count;
    return function (arg) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            self.__pull_yield(arg);
        } else {
            throw new Error("make_asio_context repeat callback");
        }
    };
};

MyActor.prototype.make_multi_context = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_multi_context not in actor");
    let contextId = self.__context_count;
    return function (...args) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            self.__post_pull(args);
        } else {
            throw new Error("make_multi_context repeat callback");
        }
    };
};

MyActor.prototype.make_asio_multi_context = function () {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_asio_multi_context not in actor");
    let contextId = self.__context_count;
    return function (...args) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            self.__pull_yield(args);
        } else {
            throw new Error("make_asio_multi_context repeat callback");
        }
    };
};

MyActor.prototype.make_timed_context = function (ms, overtimeHandler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_timed_context not in actor");
    let overtime = false;
    let contextId = self.__context_count;
    self.__timer_out(function () {
        overtime = true;
        if (overtimeHandler) {
            MyActor.check_exception_callback("make_timed_context callback error", overtimeHandler);
        }
        self.__pull_yield({ok: false});
    }, ms);
    return function (arg) {
        setImmediate(function () {
            if (contextId == self.__context_count) {
                self.__context_count++;
                if (!overtime) {
                    self.__cancel_timer();
                    self.__pull_yield({ok: true, value: arg});
                }
            } else {
                throw new Error("make_timed_context repeat callback");
            }
        });
    };
};

MyActor.prototype.make_timed_multi_context = function (ms, overtimeHandler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_timed_multi_context not in actor");
    let overtime = false;
    let contextId = self.__context_count;
    self.__timer_out(function () {
        overtime = true;
        if (overtimeHandler) {
            MyActor.check_exception_callback("make_timed_multi_context callback error", overtimeHandler);
        }
        self.__pull_yield({ok: false});
    }, ms);
    return function (...args) {
        setImmediate(function () {
            if (contextId == self.__context_count) {
                self.__context_count++;
                if (!overtime) {
                    self.__cancel_timer();
                    self.__pull_yield({ok: true, value: args});
                }
            } else {
                throw new Error("make_timed_multi_context repeat callback");
            }
        });
    };
};

MyActor.prototype.make_timed_asio_context = function (ms, overtimeHandler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_timed_asio_context not in actor");
    let overtime = false;
    let contextId = self.__context_count;
    self.__timer_out(function () {
        overtime = true;
        if (overtimeHandler) {
            MyActor.check_exception_callback("make_timed_asio_context callback error", overtimeHandler);
        }
        self.__pull_yield({ok: false});
    }, ms);
    return function (arg) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            if (!overtime) {
                self.__cancel_timer();
                self.__pull_yield({ok: true, value: arg});
            }
        } else {
            throw new Error("make_timed_asio_context repeat callback");
        }
    };
};

MyActor.prototype.make_timed_asio_multi_context = function (ms, overtimeHandler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("make_timed_asio_multi_context not in actor");
    let overtime = false;
    let contextId = self.__context_count;
    self.__timer_out(function () {
        overtime = true;
        if (overtimeHandler) {
            MyActor.check_exception_callback("make_timed_asio_multi_context callback error", overtimeHandler);
        }
        self.__pull_yield({ok: false});
    }, ms);
    return function (...args) {
        if (contextId == self.__context_count) {
            self.__context_count++;
            if (!overtime) {
                self.__cancel_timer();
                self.__pull_yield({ok: true, value: args});
            }
        } else {
            throw new Error("make_timed_asio_multi_context repeat callback");
        }
    };
};

MyActor.prototype.yield_quit_guard = function* (handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_quit_guard not in actor");
    self.lock_quit();
    yield* handler();
    yield* self.yield_unlock_quit();
};

MyActor.prototype.yield_suspend_guard = function* (handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_suspend_guard not in actor");
    self.lock_suspend();
    yield* handler();
    yield* self.yield_unlock_suspend();
};

MyActor.prototype.yield_lock_guard = function* (handle, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_lock_guard not in actor");
    yield* handle.yield_lock();
    yield* handler();
    handle.unlock();
};

MyActor.prototype.yield_shared_guard = function* (handle, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_shared_guard not in actor");
    yield* handle.yield_lock_shared();
    yield* handler();
    handle.unlock_shared();
};

MyActor.prototype.yield_pess_shared_guard = function* (handle, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_pess_shared_guard not in actor");
    yield* handle.yield_lock_pess_shared();
    yield* handler();
    handle.unlock_shared();
};

MyActor.prototype.yield_upgrade_guard = function* (handle, handler) {
    let self = this;
    if (!self.__in_actor)
        throw new Error("yield_upgrade_guard not in actor");
    yield* handle.yield_lock_upgrade();
    yield* handler();
    handle.unlock_upgrade();
};

MyActor.prototype.__make_msg_handle = function () {
    let self = this;
    return {
        __type: 2,
        __agent_handle: null,
        __ext_actor: self,
        __root_id: self.__actor_id,
        __msg_state: {
        __msg_queue: new MsgQueue(),
        __is_wait: false
        }
    };
};

MyActor.prototype.__msg_handle = function (id) {
    let self = this;
    let handle = self.__msg_table[id];
    if (!handle) {
        handle = self.__make_msg_handle();
        self.__msg_table[id] = handle;
    }
    return handle;
};

MyActor.prototype.__timer_out = function (handler, ms) {
    let self = this;
    if (!self.__timer_completed)
        throw new Error("timer error");
    if (isNaN(ms))
        throw new Error("timer number error");
    self.__timer_completed = false;
    self.__timer_timeout = ms;
    self.__timer_handler = handler;
    self.__timer_id = setTimeout(function () {
        self.__timer_id = null;
        self.__timer_completed = true;
        self.__timer_handler();
        if (self.__timer_completed)
            self.__timer_handler = null;
    }, ms);
    self.__timer_start = self.__timer_id._idleStart;
    if (undefined == self.__timer_start) {
        self.__timer_stamp();
    }
};

MyActor.prototype.__cancel_timer = function () {
    let self = this;
    if (!self.__timer_completed)
    {
        self.__timer_completed = true;
        self.__timer_handler = null;
        if (self.__timer_id) {
            clearTimeout(self.__timer_id);
            self.__timer_id = null
        }
    }
};

MyActor.prototype.__suspend_timer = function () {
    let self = this;
    if (!self.__timer_suspended) {
        self.__timer_suspended = true;
        if (!self.__timer_completed) {
            clearTimeout(self.__timer_id);
            self.__timer_id = null;
            self.__timer_end = self.__timer_stamp();
            if (self.__timer_end > self.__timer_start + self.__timer_timeout) {
                self.__timer_end = self.__timer_start + self.__timer_timeout;
            }
        }
    }
};

MyActor.prototype.__resume_timer = function () {
    let self = this;
    if (self.__timer_suspended) {
        self.__timer_suspended = false;
        if (!self.__timer_completed) {
            self.__timer_timeout -= self.__timer_end - self.__timer_start;
            self.__timer_id = setTimeout(function () {
                self.__timer_id = null;
                self.__timer_completed = true;
                self.__timer_handler();
                if (self.__timer_completed)
                    self.__timer_handler = null;
            }, self.__timer_timeout);
        }
    }
};

MyActor.prototype.__timer_stamp = function () {
    return (new Date()).valueOf() - global.__MyActor_delta_stamp;
};

MyActor.prototype.__get_tick = function () {
    return (new Date()).valueOf();
};

MyActor.prototype.__pull_yield = function (arg) {
    let self = this;
    self.__cancel_timer();
    if (!self.__is_quited) {
        if (self.__is_suspend) {
            self.__hold_pull = true;
            self.__temp_result = arg;
            return;
        }
        let old = global.__MyActor_self_actor;
        global.__MyActor_self_actor = self;
        self.__in_actor = true;
        let result;
        try {
            result = self.__top_handler.next(arg);
        } catch (err) {
            global.__MyActor_exception_handler("an uncaught actor exception:", err);
            self.__handler_stack.clear();
            self.__is_error = true;
            result = {done: true, value: err};
            self.__child_map.forEach((child, id)=> child.force_quit());
        }
        self.__in_actor = false;
        global.__MyActor_self_actor = old;
        if (result.done) {
            if (self.__handler_stack.empty()) {
                self.__is_quited = true;
                self.__result = result.value;
                if (0 == self.__child_map.size) {
                    self.__quited_to_do();
                }
            } else {
                self.__top_handler = self.__handler_stack.pop();
                self.__pull_yield(result.value);
            }
        } else if (result.value) {
            if (result.value.constructor === self.__top_handler.constructor) {
                self.__handler_stack.push(self.__top_handler);
                self.__top_handler = result.value;
                self.__pull_yield();
            }
        }
    }
};

MyActor.prototype.__tick_pull = function (arg) {
    let self = this;
    process.nextTick(function () {
        self.__pull_yield(arg);
    });
};

MyActor.prototype.__post_pull = function (arg) {
    let self = this;
    setImmediate(function () {
        self.__pull_yield(arg);
    })
};

MyActor.prototype.__notify_suspend = function (cb) {
    let self = this;
    if (!self.__is_exited) {
        self.__suspend_queue.push_back({is_suspend: true, cb: cb});
        if (!self.__lock_suspend) {
            if (1 == self.__suspend_queue.length()) {
                self.__suspend();
            }
        } else {
            self.__hold_suspended = true;
        }
    } else {
        cb();
    }
};

MyActor.prototype.__suspend = function () {
    let self = this;
    self.__suspend_timer();
    self.__is_suspend = true;
    if (self.__child_map.size) {
        let count = self.__child_map.size;
        self.__child_map.forEach((child, id)=> child.__notify_suspend(function () {
            count--;
            if (0 == count) {
                child_suspend_then();
            }
        }));
    } else {
        child_suspend_then();
    }

    function child_suspend_then() {
        self.__suspend_queue.pop_front().cb();
        if (!self.__suspend_queue.empty()) {
            if (self.__suspend_queue.front().is_suspend) {
                self.__suspend();
            } else {
                self.__resume();
            }
        }
    }
};

MyActor.prototype.__notify_resume = function (cb) {
    let self = this;
    if (!self.__is_exited) {
        self.__suspend_queue.push_back({is_suspend: false, cb: cb});
        if (!self.__lock_suspend) {
            if (1 == self.__suspend_queue.length()) {
                self.__resume();
            }
        } else {
            self.__hold_suspended = true;
        }
    } else {
        cb();
    }
};

MyActor.prototype.__resume = function () {
    let self = this;
    if (self.__child_map.size) {
        let count = self.__child_map.size;
        self.__child_map.forEach((child, id)=> child.__notify_resume(function () {
            count--;
            if (0 == count) {
                child_resume_then();
            }
        }));
    } else {
        child_resume_then();
    }

    function child_resume_then() {
        self.__suspend_queue.pop_front().cb();
        if (!self.__suspend_queue.empty()) {
            if (self.__suspend_queue.front().is_suspend) {
                self.__suspend();
            } else {
                self.__resume();
            }
        } else {
            self.__resume_timer();
            self.__is_suspend = false;
            if (self.__hold_pull) {
                self.__hold_pull = false;
                let p = self.__temp_result;
                self.__temp_result = undefined;
                self.__pull_yield(p);
            }
        }
    }
};

MyActor.prototype.__quited_to_do = function () {
    let self = this;
    self.__is_exited = true;
    for (let i in self.__msg_table) {
        let ele = self.__msg_table[i];
        ele.__ext_actor = null;
        ele.__agent_handle = null;
        if (ele.__root_id == self.__actor_id) {
            ele.__msg_state.__is_wait = false;
            while (!ele.__msg_state.__msg_queue.empty()) {
                let eleMsg = ele.__msg_state.__msg_queue.pop_front();
                if (eleMsg.reply) {
                    MyActor.check_exception_callback("msg reply error", ()=> eleMsg.reply(undefined, {err: "not processed"}));
                }
            }
        }
    }
    while (!self.__suspend_queue.empty()) {
        MyActor.check_exception_callback("suspend_queue callback error", self.__suspend_queue.pop_front().cb);
    }
    while (self.__quited_exec.length) {
        MyActor.check_exception_callback("quited_exec callback error", self.__quited_exec.pop());
    }
    while (!self.__quited_notify.empty()) {
        MyActor.check_exception_callback("quited_notify error", self.__quited_notify.pop_front());
    }
    if (self.__quited_callback) {
        MyActor.check_exception_callback("quited_callback error",
            ()=> !self.__is_error ? self.__quited_callback(self.__result) : self.__quited_callback(undefined, self.__result));
        self.__quited_callback = null;
    }
    if (self.__is_error) {
        while (!self.__error_notify.empty()) {
            MyActor.check_exception_callback("error_callback error", self.__error_notify.pop_front());
        }
    } else {
        self.__error_notify.clear();
    }
    self.__temp_result = undefined;
    self.__suspend_queue = null;
    self.__top_handler = null;
    self.__handler_stack = null;
    self.__quited_notify = null;
    self.__error_notify = null;
    self.__child_map = null;
};

MyActor.prototype.__child_quited_handler = function (child) {
    let self = this;
    self.__child_map.delete(child.__actor_id);
    if (0 == self.__child_map.size) {
        if (self.__is_quited) {
            self.__quited_to_do();
        }
    }
};

/////////////////////////////////////////////////////////end///////////////////////////////////////////////////////////

exports.MsgQueue = MsgQueue;
exports.Stack  = Stack;
exports.List = List;
exports.Channel = Channel;
exports.Csp = Csp;
exports.Mutex = Mutex;
exports.SharedMutex = SharedMutex;
exports.MyActor = MyActor;
exports.create =  MyActor.create;
exports.bind = MyActor.bind;
exports.sleep = MyActor.sleep;
exports.tick = MyActor.tick;
exports.time_string = MyActor.time_string;
exports.tick_string = MyActor.tick_string;
exports.self_actor = MyActor.self_actor;
exports.create_queue = MyActor.create_queue;
exports.create_stack = MyActor.create_stack;
exports.create_list = MyActor.create_list;
exports.create_async_queue = MyActor.create_async_queue;
exports.register_exception_handler = MyActor.register_exception_handler;
exports.wrap_hold_work = MyActor.wrap_hold_work;
exports.hold_work = MyActor.hold_work;
exports.release_work = MyActor.release_work;
exports.force_trace_error_stack = MyActor.force_trace_error_stack;
exports.enable_source_map_trace = MyActor.enable_source_map_trace;
exports.check_exception_callback = MyActor.check_exception_callback;
exports.make_mutex = MyActor.make_mutex;
exports.make_shared_mutex = MyActor.make_shared_mutex;
exports.make_condition_variable = MyActor.make_condition_variable;
exports.trace = MyActor.trace;
exports.trace_flush = MyActor.trace_flush;
exports.trace_space = MyActor.trace_space;
exports.trace_comma = MyActor.trace_comma;
exports.wrap_post = MyActor.wrap_post;
exports.wrap_post_target = MyActor.wrap_post_target;
exports.wrap_tick = MyActor.wrap_tick;
exports.wrap_tick_target = MyActor.wrap_tick_target;